import datetime

from coin.exchange.base.kr_rest.derivative_util import (PERPETUAL_DATE)
from coin.exchange.okex_futures.kr_rest.futures_constants import (contract_type_list,
                                                                  quarter_contract_date)
import coin.exchange.okex_futures.kr_rest.exp_util as exp_util


def find_contract_type_from_expiry(current_datetime, expiry):
  if expiry == PERPETUAL_DATE:
    return 'perpetual'

  expiry = exp_util.expiry_accurate_datetime(expiry)
  time_delta = expiry - current_datetime
  # At least 10 minutes before expiration.
  assert time_delta > datetime.timedelta(minutes=10)
  if time_delta <= datetime.timedelta(days=7):
    return 'this_week'
  elif datetime.timedelta(days=7) < time_delta <= datetime.timedelta(days=14):
    return 'next_week'
  elif expiry == find_expiry_from_contract_type(current_datetime, 'quarter'):
    return 'quarter'
  elif expiry == find_expiry_from_contract_type(current_datetime, 'next_quarter'):
    return 'next_quarter'
  else:
    raise ValueError(current_datetime, expiry)


def find_expiry_from_contract_type(current_datetime, contract_type):
  if contract_type == 'perpetual':
    return PERPETUAL_DATE

  assert contract_type in contract_type_list
  if contract_type == 'this_week':
    return exp_util.find_this_week_contract_expiring_date(current_datetime)
  elif contract_type == 'next_week':
    return exp_util.find_next_week_contract_expiring_date(current_datetime)
  elif contract_type == 'quarter':
    return exp_util.find_quarter_contract_expiring_date(quarter_contract_date, current_datetime)
  elif contract_type == 'next_quarter':
    return exp_util.find_next_quarter_contract_expiring_date(quarter_contract_date,
                                                             current_datetime)
  else:
    raise ValueError(current_datetime, contract_type)


def to_expiry_contract_type(expiry_str, current_datetime):
  if expiry_str == 'perpetual':
    expiry = PERPETUAL_DATE
    contract_type = 'perpetual'
  elif expiry_str in ['week']:
    contract_type = 'this_week'
    expiry = find_expiry_from_contract_type(current_datetime, contract_type)
  elif expiry_str in contract_type_list:
    contract_type = expiry_str
    expiry = find_expiry_from_contract_type(current_datetime, contract_type)
  elif expiry_str.isdigit():
    expiry = datetime.datetime.strptime(expiry_str, '%Y%m%d')
    contract_type = find_contract_type_from_expiry(current_datetime, expiry)
  else:
    raise ValueError(expiry_str, current_datetime)
  return expiry, contract_type


def guess_expiry(expiry_str, current_datetime):
  expiry = datetime.datetime.strptime(expiry_str, '%m%d')
  # Settle time is utc 8am on Friday.
  expiry = datetime.datetime(current_datetime.year, expiry.month, expiry.day, hour=8)
  if expiry <= current_datetime:
    expiry = datetime.datetime(current_datetime.year + 1, expiry.month, expiry.day)
  assert expiry.weekday() == 4

  return expiry


def parse_native_expiry_contract_type(expiry_str, current_datetime):
  if expiry_str == 'SWAP':
    expiry = PERPETUAL_DATE
    contract_type = 'perpetual'
  else:
    expiry = guess_expiry(expiry_str, current_datetime)
    contract_type = find_contract_type_from_expiry(current_datetime, expiry)
  return expiry, contract_type


def guess_expiry_v3(expiry_str, current_datetime):
  expiry = datetime.datetime.strptime(expiry_str, '%y%m%d')
  # Settle time is utc 8am on Friday.
  expiry = datetime.datetime(expiry.year, expiry.month, expiry.day, hour=8)
  assert expiry.weekday() == 4
  return expiry


def parse_native_expiry_contract_type_v3(expiry_str, current_datetime):
  if expiry_str == 'SWAP':
    expiry = PERPETUAL_DATE
    contract_type = 'perpetual'
  else:
    expiry = guess_expiry_v3(expiry_str, current_datetime)
    contract_type = find_contract_type_from_expiry(current_datetime, expiry)
  return expiry, contract_type


def to_native_expiry_str(expiry, contract_type):
  if contract_type == 'perpetual':
    assert expiry == PERPETUAL_DATE
    return 'SWAP'
  elif contract_type in contract_type_list:
    return expiry.strftime('%m%d')
  else:
    raise ValueError(contract_type)


def to_native_expiry_str_v3(expiry, contract_type):
  if contract_type == 'perpetual':
    assert expiry == PERPETUAL_DATE
    return 'SWAP'
  elif contract_type in contract_type_list:
    return expiry.strftime('%y%m%d')
  else:
    raise ValueError(contract_type)
